/*
 * <copyright>
 *
 * Copyright (c) 2007 Dieter Moroff and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Dieter Moroff - Initial API and implementation
 *
 * </copyright>
 */
package org.openarchitectureware.adapter.rsdp.plugin;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.xtend.expression.TypeSystem;
import org.eclipse.xtend.shared.ui.MetamodelContributor;
import org.eclipse.xtend.typesystem.MetaModel;
import org.eclipse.xtend.typesystem.uml2.profile.ProfileMetaModel;
import org.osgi.framework.Bundle;

/**
 * Contributor to UML2 metamodels for IBM Rational Software Architect /
 * Modeller. Read all profiles regsitered at the extenstionpoint
 * 
 * <pre>
 * com.ibm.xtools.uml.msl.UMLProfiles
 * </pre>.
 * 
 * @author Dieter Moroff (10.01.2007) (Last change $Author: kthoms $ $Date:
 *         2007/02/24 11:21:49 $)
 */
public class Uml2MetamodelContributor implements MetamodelContributor {
	private static final String rsdpProfileExtensionPointId = "com.ibm.xtools.uml.msl.UMLProfiles";

	private static List<MetaModel> pluginMetamodels = null;

	/**
	 * 
	 */
	public MetaModel[] getMetamodels(IJavaProject project, TypeSystem ctx) {
		loadPluginMetamodels();
		return pluginMetamodels.toArray(new MetaModel[pluginMetamodels.size()]);
	}

	/**
	 * Load the metamodels from the rsa/rsm profile extension point
	 */
	private void loadPluginMetamodels() {
		if (pluginMetamodels == null) {
			pluginMetamodels = new ArrayList<MetaModel>();

			IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry();
			IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(rsdpProfileExtensionPointId);
			if (extensionPoint != null) {
				IExtension extensions[] = extensionPoint.getExtensions();

				for (int i = 0; i < extensions.length; i++) {
					IExtension extension = extensions[i];
					IConfigurationElement elements[] = extension.getConfigurationElements();
					String pluginId = extension.getNamespaceIdentifier();

					for (int j = 0; j < elements.length; j++) {
						IConfigurationElement element = elements[j];
						String profilePath = element.getAttribute("path");

						String msg = "Added profile " + profilePath + " from " + pluginId;
						Activator.logInfo(msg);
						// TODO Logging to a better place
						System.out.println(msg);

						// Open the profile
						URI profileURI = URI.createURI(profilePath, true);

						try {
							if (profileURI.scheme() == null) {
								Bundle bundle = Platform.getBundle(pluginId);
								URL profileURL = bundle.getResource(profilePath);
								profileURI = URI.createURI(profileURL.toURI().toString());
							}
							ResourceSet resourceSet = new ResourceSetImpl();
							resourceSet.setURIConverter(new PathMapURIConverter(resourceSet.getURIConverter()));
							Resource resource = resourceSet.getResource(profileURI, true);

							try {
								resource.load(null);
							} catch (IOException e) {
								e.printStackTrace();
							}

							EList<Resource.Diagnostic> errors = resource.getErrors();
							for (Iterator<Resource.Diagnostic> ie = errors.iterator(); ie.hasNext();) {
								Resource.Diagnostic error = ie.next();

								Activator.logError(error.toString());
							}

							for (Iterator<Resource.Diagnostic> iw = resource.getWarnings().iterator(); iw.hasNext();) {
								Resource.Diagnostic warning = iw.next();

								Activator.logWarning(warning.toString());
							}
							EList<EObject> list = resource.getContents();
							Iterator<EObject> contentIterator = list.iterator();
							if (contentIterator.hasNext()) {
								EObject modelElement = contentIterator.next();

								if (modelElement instanceof Profile) {
									Profile profile = (Profile) modelElement;

									pluginMetamodels.add(new ProfileMetaModel(profile));
									Activator.logInfo("Added profile " + profile.getName());
								}
							}
						} catch (URISyntaxException e) {
							e.printStackTrace();
						} catch (RuntimeException e) {
							Activator.logError(e.toString());
						} finally {
						}
					}
				}

			}
		}

	}

}
